package KNN;

import typydanych.Wektor;

public class FabrykaMetryk {
	public static final int EUKLIDESOWA = 0;
	public static final int ULICZNA = 1;
	public static final int CZEBYSZEWA = 2;
	
	public static IMetryka wezMetryke(int typ){
		switch(typ){
		case 0:
			return new MetrykaEuklidesowa();
		case 1:
			return new MetrykUliczna();
		case 2:
			return new MetrykaCzebyszewa();
		}
		return null;
	}
	
	public static String nazwaMetryki(IMetryka metryka){
		switch(metryka.typ()){
		case 0:
			return "EUKLIDESOWA";
		case 1:
			return "ULICZNA";
		case 2:
			return "CZEBYSZEWA";
		default:
			return null;
		}
	}
	
	private static class MetrykaEuklidesowa implements IMetryka {

		private final int type = FabrykaMetryk.EUKLIDESOWA;

		@Override
		public double policzDystans(Wektor x, Wektor w) {
			double sum = 0.0;
			for (int i = 0; i < w.getWektor().length; i++) {
				sum += Math.pow(x.getWektor()[i]-w.getWektor()[i], 2);
			}
			return Math.sqrt(sum);
		}

		@Override
		public int typ() {
			return this.type;
		}
		
		@Override
		public String toString(){
			return FabrykaMetryk.nazwaMetryki(this);
		}
		
	}
	
	private static class MetrykUliczna implements IMetryka {

		private final int type = FabrykaMetryk.ULICZNA;

		@Override
		public double policzDystans(Wektor x, Wektor w) {
			double sum = 0.0;
			for (int i = 0; i < w.getWektor().length; i++) {
				sum += Math.abs(x.getWektor()[i]-w.getWektor()[i]);
			}
			return sum;
		}

		@Override
		public int typ() {
			return this.type;
		}
		@Override
		public String toString(){
			return FabrykaMetryk.nazwaMetryki(this);
		}
		
	}
	
	private static class MetrykaCzebyszewa implements IMetryka {

		private final int type = FabrykaMetryk.CZEBYSZEWA;

		@Override
		public double policzDystans(Wektor x, Wektor w) {
			double max = Double.MIN_VALUE;
			double newMax = 0.0;
			for (int i = 0; i < w.getWektor().length; i++) {
				newMax = Math.abs(x.getWektor()[i] - w.getWektor()[i]);
				if(max < newMax)
					max = newMax;
			}
			return max;
		}

		@Override
		public int typ() {
			return this.type;
		}
		@Override
		public String toString(){
			return FabrykaMetryk.nazwaMetryki(this);
		}
		
	}
	
	
}
